package rpc_service

import (
	"context"
	"github.com/chicken-team-outside/chicken_transmission/api_messages"
	"github.com/chicken-team-outside/chicken_transmission/proxy_server/model"
	"github.com/golang/protobuf/proto"
	"go.uber.org/zap"
	"time"
)

func init() {
	model.AddTransportHook = func(info *model.TransportInfo) {
		notifyClientChange(api_messages.MessageType_AddClient, info)
	}
	model.UpdateTransportHook = func(info *model.TransportInfo) {
		notifyClientChange(api_messages.MessageType_UpdateClientInfo, info)
	}
	model.RemoveTransportHook = func(info *model.TransportInfo) {
		notifyClientChange(api_messages.MessageType_RemoveClient, info)
	}
}

func sendClientList(info *model.TransportInfo, ctx context.Context) bool {
	infos, err := model.GetUserTransportInfos(info.UserId)
	if err == nil {
		reply := &api_messages.ListClientReply{
			Info: make([]*api_messages.ClientStatusInfo, len(infos)),
		}
		for i, item := range infos {
			reply.Info[i] = &api_messages.ClientStatusInfo{
				Info: &api_messages.TransportInfo{
					Id:         item.Id,
					Title:      item.Title,
					IsActive:   item.IsActive,
					UpdateTime: item.UpdatedTime.UnixMilli(),
				},
				OnlineStatus: getTransportOnlineStatus(item.Id),
			}
			if item.Token == info.Token {
				reply.Info[i].Info.Token = info.Token
			}
		}
		err = sendMsgToClient(ctx, 0, info.Id, api_messages.MessageType_ListAllClientStatus, reply)
		if err != nil {
			zap.L().Debug("failed to send all client status to client", zap.Error(err), zap.Uint64("client_id", info.Id))
		}
	} else {
		zap.L().Warn("failed to get user transport infos", zap.Error(err), zap.Uint64("client_id", info.Id))
	}
	return err == nil
}

func getTransportOnlineStatus(id uint64) *api_messages.TransportOnlineStatus {
	return &api_messages.TransportOnlineStatus{
		Id:         id,
		Online:     GetClient(id) != nil,
		UpdateTime: time.Now().UnixMilli(),
	}
}

func notifyClientOnline(usrId uint64, clientId uint64) {
	broadcastMsgToAllClientByUser(clientId, usrId, context.Background(), api_messages.MessageType_UpdateClientStatus, getTransportOnlineStatus(clientId))
}

func notifyClientChange(msgType api_messages.MessageType, info *model.TransportInfo) {
	var msg proto.Message
	if msgType == api_messages.MessageType_RemoveClient {
		msg = &api_messages.TransportOnlineStatus{
			Id: info.Id,
		}
	} else {
		msg = &api_messages.ClientStatusInfo{
			Info: &api_messages.TransportInfo{
				Id:         info.Id,
				Title:      info.Title,
				IsActive:   info.IsActive,
				UpdateTime: info.UpdatedTime.UnixMilli(),
			},
			OnlineStatus: getTransportOnlineStatus(info.Id),
		}
	}
	broadcastMsgToAllClientByUser(0, info.UserId, context.Background(), msgType, msg)
}
